﻿using System;
using System.Collections.Generic;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.Utils;

namespace Sustainalytics.GCCS.DataAccessLayer
{
    public class GCCSDataReader : IGCCSDataReader
    {
        private readonly IGCCSDbContext _gccsDbContext;

        protected GCCSDataReader(IGCCSDbContext gccsDbContext)
        {
            _gccsDbContext = gccsDbContext;
        }

        public static IGCCSDataReader GetInstance(string gccsConnectionString, int commandTimeout)
        {
            if (string.IsNullOrEmpty(gccsConnectionString))
                throw new ArgumentException("A connection string for GCCS database must be provided to create an GCCSDataReader instance!");

            if (commandTimeout == -1)
            {
                commandTimeout = SyncHelper.ReadCommandTimeOutFromConfig();
            }

            return new GCCSDataReader(new GCCSDbContext(gccsConnectionString, commandTimeout));
        }

        public GCCurrentQuarter GetCurrentQuarter()
        {
            GCCurrentQuarter currentQuarter = null;

            try
            {
                using (var reader = _gccsDbContext.CurrentQuarter())
                {
                    if (reader == null) return null;

                    while (reader.Read())
                    {
                        var quarter = (DateTime) reader["Date"];
                        var publishedDate = (DateTime) reader["PublishedDateTime"];

                        currentQuarter = new GCCurrentQuarter();

                        currentQuarter.Id = Guid.NewGuid();
                        currentQuarter.Date = new DateTime(quarter.Year, quarter.Month, quarter.Day, 0, 0, 0, 0,
                            DateTimeKind.Utc);
                        currentQuarter.IsClosed = (bool) reader["IsClosed"];
                        currentQuarter.IsPublished = (bool) reader["IsPublished"];
                        currentQuarter.PublishedDateTime =
                            new DateTime(publishedDate.Year, publishedDate.Month, publishedDate.Day,
                                publishedDate.Hour, publishedDate.Minute, publishedDate.Second,
                                publishedDate.Millisecond, DateTimeKind.Utc);
                    }
                }
            }
            catch 
            {
                //todo Soryn to be removed after final implementation
            }

            return currentQuarter;
        }

        public virtual List<GCOverallCompanySummary> GetOverallCompaniesSummary()
        {
            var overallCompaniesSummary = new List<GCOverallCompanySummary>();

            using (var reader = _gccsDbContext.OverallCompaniesSummary())
            {
                if (reader == null) return overallCompaniesSummary;

                while (reader.Read())
                {
                    overallCompaniesSummary.Add(new GCOverallCompanySummary
                    {
                        Id = (Guid)reader["CompanyId"],
                        GCSignatorySince = reader.IsDBNull(reader.GetOrdinal("GccsSignatorySince"))
                            ? null
                            : (DateTime?)reader["GccsSignatorySince"],
                        OverallCompanyAssessment = (GCAssessment)reader["OverallCompanyAssessment"],
                        OverallCompanyAssessmentEffectiveSince = (DateTime)reader["OverallCompanyAssessmentEffectiveSince"],
                        LastUpdated = (DateTime)reader["LastUpdated"], 
                        ReasonForNonCompliance = reader["ReasonForNonCompliance"] as string
                    });
                }
            }

            return overallCompaniesSummary;
        }

        public virtual List<GCPrincipleSummaryExtended> GetPrinciplesSummaryExtended()
        {
            var principlesSummary = new List<GCPrincipleSummaryExtended>();

            using (var reader = _gccsDbContext.PrinciplesSummary())
            {
                if (reader == null) return principlesSummary;

                while (reader.Read())
                {
                    var gcPrinciple = new GCPrincipleSummaryExtended();


                    gcPrinciple.Id = Guid.NewGuid();
                    gcPrinciple.CompanyId = (Guid) reader["CompanyId"];

                    gcPrinciple.Principle = new GCPrincipleTemplate
                    {
                        Id = (int) reader["PrincipleTemplateId"],
                        Name = (string) reader["PrincipleGccsName"],
                        Description = (string) reader["PrincipleGccsDescription"],
                        Pillar = new GCPillarTemplate
                        {
                            Id = (int) reader["PillarId"],
                            Name = (string) reader["PillarName"],
                        }
                    };

                    gcPrinciple.Issue = (string) reader["Issue"];
                    gcPrinciple.PrincipleAssessment = (GCAssessment) reader["PrincipleAssessment"];
                    gcPrinciple.PrincipleAssessmentEffectiveSince = (DateTime) reader["PrincipleAssessmentEffectiveSince"];

                    gcPrinciple.AssessmentSummaryAndConclusionIntroductionSentence =
                        (string) reader["AssessmentSummaryAndConclusionIntroductionSentence"];
                    
                    gcPrinciple.AssessmentComments = new List<string>();

                    if(!reader.IsDBNull(reader.GetOrdinal("AssessmentComment1")))
                        gcPrinciple.AssessmentComments.Add((string)reader["AssessmentComment1"]);

                    if (!reader.IsDBNull(reader.GetOrdinal("AssessmentComment2")))
                        gcPrinciple.AssessmentComments.Add((string)reader["AssessmentComment2"]);

                    if (!reader.IsDBNull(reader.GetOrdinal("AssessmentComment3")))
                        gcPrinciple.AssessmentComments.Add((string)reader["AssessmentComment3"]);

                    if (!reader.IsDBNull(reader.GetOrdinal("AssessmentComment4")))
                        gcPrinciple.AssessmentComments.Add((string)reader["AssessmentComment4"]);

                    if (!reader.IsDBNull(reader.GetOrdinal("AssessmentComment5")))
                        gcPrinciple.AssessmentComments.Add((string)reader["AssessmentComment5"]);

                    if (!reader.IsDBNull(reader.GetOrdinal("AssessmentComment6")))
                        gcPrinciple.AssessmentComments.Add((string)reader["AssessmentComment6"]);
                    
                    principlesSummary.Add(gcPrinciple);
                }

            }

            return principlesSummary;
        }

        public virtual List<GCPrincipleEventIndicatorExtended> GetPrincipleEventIndicators()
        {
            var principleEventIndicators = new List<GCPrincipleEventIndicatorExtended>();

            using (var reader = _gccsDbContext.PrincipleEventIndicators())
            {
                while (reader.Read())
                {
                    var principleEventIndicator = new GCPrincipleEventIndicatorExtended();

                    principleEventIndicator.Id = Guid.NewGuid();
                    principleEventIndicator.CompanyId = (Guid) reader["CompanyId"];
                    principleEventIndicator.PrincipleTemplateId = (int) reader["PrincipleTemplateId"];

                    principleEventIndicator.IssueType = (string) reader["IssueType"];
                    principleEventIndicator.EventIndicatorAssessment = (GCAssessment) reader["EventIndicatorAssessment"];

                    principleEventIndicator.EventSummary = (string) reader["EventSummary"];

                    principleEventIndicator.ImpactSummary = (string) reader["ImpactSummary"];

                    principleEventIndicator.ImpactComments = new List<string>();
                    if (!reader.IsDBNull(reader.GetOrdinal("ImpactComment1")))
                        principleEventIndicator.ImpactComments.Add((string)reader["ImpactComment1"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ImpactComment2")))
                        principleEventIndicator.ImpactComments.Add((string)reader["ImpactComment2"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ImpactComment3")))
                        principleEventIndicator.ImpactComments.Add((string)reader["ImpactComment3"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ImpactComment4")))
                        principleEventIndicator.ImpactComments.Add((string)reader["ImpactComment4"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ImpactComment5")))
                        principleEventIndicator.ImpactComments.Add((string)reader["ImpactComment5"]);

                    principleEventIndicator.ManagementSummary = (string) reader["ManagementSummary"];
                    
                    principleEventIndicator.ManagementComments = new List<string>();
                    if (!reader.IsDBNull(reader.GetOrdinal("ManagementComment1")))
                        principleEventIndicator.ManagementComments.Add((string)reader["ManagementComment1"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ManagementComment2")))
                        principleEventIndicator.ManagementComments.Add((string)reader["ManagementComment2"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ManagementComment3")))
                        principleEventIndicator.ManagementComments.Add((string)reader["ManagementComment3"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ManagementComment4")))
                        principleEventIndicator.ManagementComments.Add((string)reader["ManagementComment4"]);
                    if (!reader.IsDBNull(reader.GetOrdinal("ManagementComment5")))
                        principleEventIndicator.ManagementComments.Add((string)reader["ManagementComment5"]);

                    principleEventIndicators.Add(principleEventIndicator);
                }
            }

            return principleEventIndicators;
        }

        public virtual List<GCSource> GetSources()
        {
            var sources = new List<GCSource>();

            using (var reader = _gccsDbContext.Sources())
            {
                while (reader.Read())
                {
                    var source = new GCSource();

                    source.Id = Guid.NewGuid();
                    source.CompanyId = (Guid)reader["CompanyId"];
                    source.Type = (int)reader["Type"];
                    source.EventIndicatorAssessment = (GCAssessment)reader["EventIndicatorAssessment"];
                    source.PublicationDate = (DateTime)reader["PublicationDate"];
                    source.NewsArticleName = (string)reader["NewsArticleName"];
                    source.SourceName = (string)reader["SourceName"];

                    sources.Add(source);
                }
            }
            return sources;
        }
    }
}
